ggthemes
First let’s look at a simple scatterplot made by geom_point() and with no themes:
p <- ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
ggtitle("Cars")
p

p2 <- ggplot(mtcars, aes(x = wt, y = mpg, color = factor(gear))) +
geom_point() +
labs(title = "Cars", color = "Gear")
p2

Tufte theme and geoms
Minimal theme and geoms based on plots in The Visual Display of Quantitative Information.
p + geom_rangeframe() +
theme_tufte()

Economist theme
A theme that approximates the style of plots in The Economist magazine.
p + theme_economist() + scale_colour_economist()

Excel 2003 theme
For that classic ugly look and feel
p2 + theme_excel() + scale_colour_excel()

Wall Street Journal
Theme and some color palettes based on plots in the The Wall Street Journal.
p2 + theme_wsj() + scale_colour_wsj("colors6", "")

Template for layered grammar of graphics
```ggplot(data = ) + ( mapping = aes(), stat = , position = ) + +
In practice, you rarely need to supply all seven parameters to make a graph because ggplot2 will provide useful defaults for everything except the data, the mappings, and the geom function.
----
## More Examples
**Bar Chart** from [Top 50 ggplot2 Visualizations](http://r-statistics.co/Top50-Ggplot2-Visualizations-MasterList-R-Code.html).
We saw how to create a bar chart with `geom_bar()`. By default `geom_bar()` will use `stat = "count"`, so we don't need to provide a `y`, it's being calculated as the count of points in each bin. In order to create a bar chart with a given `y` value we need to set `stat=identity` and provide both `x` and `y` inside `aes()` `x` is either character or factor and `y` is numeric.
<!-- rnb-text-end -->
<!-- rnb-chunk-begin -->
<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuIyBjcmVhdGUgYSBmcmVxdWVuY3kgdGFibGVcbmZyZXF0YWJsZSA8LSB0YWJsZShtcGckbWFudWZhY3R1cmVyKVxuZGYgPC0gYXMuZGF0YS5mcmFtZS50YWJsZShmcmVxdGFibGUpXG5oZWFkKGRmKVxuYGBgIn0= -->
```r
# create a frequency table
freqtable <- table(mpg$manufacturer)
df <- as.data.frame.table(freqtable)
head(df)
ggplot(df, aes(Var1, Freq)) +
geom_bar(stat="identity", width = 0.5, fill="tomato2") +
labs(title="Bar Chart",
subtitle="Manufacturer of vehicles",
caption="Source: Frequency of Manufacturers from 'mpg' dataset",
x = "Manufacturer") +
theme_classic() +
theme(axis.text.x = element_text(angle=65, vjust=0.6)) # to give x labels an angle for readability

Email Campaign Funnel from Top 50 ggplot2 Visualizations:
options(scipen = 999) # turns off scientific notations like 1e+40
options(repr.plot.width=7, repr.plot.height=5) # Modifying the chart size
# Read data
options(readr.num_columns = 0) # turns off messages printed by read_csv
email_campaign_funnel <- read_csv("https://raw.githubusercontent.com/selva86/datasets/master/email_campaign_funnel.csv")
Rows: 42 Columns: 3
── Column specification ───────────────────────────────────────────────────────────
Delimiter: ","
chr (2): Stage, Gender
dbl (1): Users
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# X Axis Breaks and Labels
brks <- seq(-15000000, 15000000, 5000000)
lbls = paste0(as.character(c(seq(15, 0, -5), seq(5, 15, 5))), "m")
# Plot
ggplot(email_campaign_funnel, aes(x = Stage, y = Users, fill = Gender)) + # Fill column
geom_bar(stat = "identity", width = .6) + # draw the bars
scale_y_continuous(breaks = brks, # Breaks
labels = lbls) + # Labels
coord_flip() + # Flip axes
labs(title = "Email Campaign Funnel") +
theme_tufte() + # Tufte theme from ggfortify
theme(plot.title = element_text(hjust = .5),
axis.ticks = element_blank()) # Centre plot title

Line chart
dtemp <- data.frame(months = factor(rep(substr(month.name,1,3), 4), levels = substr(month.name,1,3)),
city = rep(c("Tokyo", "New York", "Berlin", "London"), each = 12),
temp = c(7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6,
-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5,
-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0,
3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8))
temp <- ggplot(dtemp, aes(x = months, y = temp, group = city, color = city)) +
geom_line() +
geom_point(size = 1.1) +
ggtitle("Monthly Average Temperature") +
theme_hc(style = "darkunica") +
scale_fill_hc("darkunica")
temp

Interactive plotting with Plotly
We can use package plotly on top of a ggplot plot to create interactive charts. Plotly is a powerful tool for creating interactive dashboards and plots and there are different ways to use it. Here we will only show how to make ggplots into a plotly by using ggplotly() function. For more information about other ways to leverage this package go to ploy.ly.
Scatterplot
Let’s use the most recent plot we created with WSJ theme as an example:
ggplotly(p2 + theme_wsj() + scale_colour_wsj("colors6", "")) # Same plot with ggplotly()
Time Series
Using geom_line(), a time series (or line chart) can be drawn. Data: economics from ggplot2.
head(economics)
ts_plot <- ggplot(economics, aes(x=date)) +
geom_line(aes(y=psavert)) +
labs(title="US economic time series",
subtitle = "Personal Savings Rate",
caption="Source: Economics",
y="Savings Rate %") +
theme_classic()
ggplotly(ts_plot) # Same plot with ggplotly()
Bar chart
bar_plot <- ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, fill = clarity), position = "dodge") +
scale_fill_manual(values = c("#41f4f4", "#41d9f4", "#41bbf4", "#418ef4", "#415ef4", "#6a41f4", "#9741f4", "#f441f1"))
ggplotly(bar_plot) # Same plot with ggplotly()
LS0tCnRpdGxlOiAiVGhlbWUiCnN1YnRpdGxlOiAiRGF0YSBWaXN1YWxpemF0aW9uIC0gUGFydCA3IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQojIGxvYWRpbmcgbGlicmFyaWVzCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdndGhlbWVzKQpsaWJyYXJ5KHBsb3RseSkKCiMgbW9kaWZ5aW5nIGNoYXJ0IHNpemUKb3B0aW9ucyhyZXByLnBsb3Qud2lkdGg9NSwgcmVwci5wbG90LmhlaWdodD0zKQpgYGAKCjxjZW50ZXI+ICFbXSguLi9wbmcvbGF5ZXJzLW9mLWdncGxvdC5wbmcpe3dpZHRoPTQwMH0gPC9jZW50ZXI+CgojIyMgZ2d0aGVtZXMKRmlyc3QgbGV0J3MgbG9vayBhdCBhIHNpbXBsZSBzY2F0dGVycGxvdCBtYWRlIGJ5IGBnZW9tX3BvaW50KClgIGFuZCB3aXRoIG5vIHRoZW1lczoKCmBgYHtyfQpwIDwtIGdncGxvdChtdGNhcnMsIGFlcyh4ID0gd3QsIHkgPSBtcGcpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZ3RpdGxlKCJDYXJzIikKcApgYGAKYGBge3J9CnAyIDwtIGdncGxvdChtdGNhcnMsIGFlcyh4ID0gd3QsIHkgPSBtcGcsIGNvbG9yID0gZmFjdG9yKGdlYXIpKSkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh0aXRsZSA9ICJDYXJzIiwgY29sb3IgPSAiR2VhciIpCnAyCmBgYAoKCiMjIyMgVHVmdGUgdGhlbWUgYW5kIGdlb21zCk1pbmltYWwgdGhlbWUgYW5kIGdlb21zIGJhc2VkIG9uIHBsb3RzIGluIFRoZSBWaXN1YWwgRGlzcGxheSBvZiBRdWFudGl0YXRpdmUgSW5mb3JtYXRpb24uCgpgYGB7cn0KcCArIGdlb21fcmFuZ2VmcmFtZSgpICsKICB0aGVtZV90dWZ0ZSgpCmBgYAoKIyMjIyBFY29ub21pc3QgdGhlbWUKQSB0aGVtZSB0aGF0IGFwcHJveGltYXRlcyB0aGUgc3R5bGUgb2YgcGxvdHMgaW4gVGhlIEVjb25vbWlzdCBtYWdhemluZS4KCmBgYHtyfQpwICsgdGhlbWVfZWNvbm9taXN0KCkgKyBzY2FsZV9jb2xvdXJfZWNvbm9taXN0KCkgCmBgYAoKIyMjIyBFeGNlbCAyMDAzIHRoZW1lCkZvciB0aGF0IGNsYXNzaWMgdWdseSBsb29rIGFuZCBmZWVsCgpgYGB7cn0KcDIgKyB0aGVtZV9leGNlbCgpICsgc2NhbGVfY29sb3VyX2V4Y2VsKCkKYGBgCgojIyMjIFdhbGwgU3RyZWV0IEpvdXJuYWwKVGhlbWUgYW5kIHNvbWUgY29sb3IgcGFsZXR0ZXMgYmFzZWQgb24gcGxvdHMgaW4gdGhlIFRoZSBXYWxsIFN0cmVldCBKb3VybmFsLgoKYGBge3J9CnAyICsgdGhlbWVfd3NqKCkgKyBzY2FsZV9jb2xvdXJfd3NqKCJjb2xvcnM2IiwgIiIpCmBgYAoKIyMjIENyZWF0ZSB5b3VyIG93biB0aGVtZQoKYGBge3J9CmJsYW5rX3RoZW1lIDwtIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBmYWNlPSJib2xkIikKICAgICkKYGBgCgpgYGB7cn0KcCArIGJsYW5rX3RoZW1lCmBgYAoKCiMjIFRlbXBsYXRlIGZvciBsYXllcmVkIGdyYW1tYXIgb2YgZ3JhcGhpY3MKCgo+IGBgYGdncGxvdChkYXRhID0gPERBVEE+KSArIAogIDxHRU9NX0ZVTkNUSU9OPigKICAgICBtYXBwaW5nID0gYWVzKDxNQVBQSU5HUz4pLAogICAgIHN0YXQgPSA8U1RBVD4sIAogICAgIHBvc2l0aW9uID0gPFBPU0lUSU9OPgogICkgKwogIDxDT09SRElOQVRFX0ZVTkNUSU9OPiArCiAgPEZBQ0VUX0ZVTkNUSU9OPgpgYGAKCkluIHByYWN0aWNlLCB5b3UgcmFyZWx5IG5lZWQgdG8gc3VwcGx5IGFsbCBzZXZlbiBwYXJhbWV0ZXJzIHRvIG1ha2UgYSBncmFwaCBiZWNhdXNlIGdncGxvdDIgd2lsbCBwcm92aWRlIHVzZWZ1bCBkZWZhdWx0cyBmb3IgZXZlcnl0aGluZyBleGNlcHQgdGhlIGRhdGEsIHRoZSBtYXBwaW5ncywgYW5kIHRoZSBnZW9tIGZ1bmN0aW9uLgoKLS0tLQoKIyMgTW9yZSBFeGFtcGxlcwoKKipCYXIgQ2hhcnQqKiBmcm9tIFtUb3AgNTAgZ2dwbG90MiBWaXN1YWxpemF0aW9uc10oaHR0cDovL3Itc3RhdGlzdGljcy5jby9Ub3A1MC1HZ3Bsb3QyLVZpc3VhbGl6YXRpb25zLU1hc3Rlckxpc3QtUi1Db2RlLmh0bWwpLgoKV2Ugc2F3IGhvdyB0byBjcmVhdGUgYSBiYXIgY2hhcnQgd2l0aCBgZ2VvbV9iYXIoKWAuIEJ5IGRlZmF1bHQgYGdlb21fYmFyKClgIHdpbGwgdXNlIGBzdGF0ID0gImNvdW50ImAsIHNvIHdlIGRvbid0IG5lZWQgdG8gcHJvdmlkZSBhIGB5YCwgaXQncyBiZWluZyBjYWxjdWxhdGVkIGFzIHRoZSBjb3VudCBvZiBwb2ludHMgaW4gZWFjaCBiaW4uIEluIG9yZGVyIHRvIGNyZWF0ZSBhIGJhciBjaGFydCB3aXRoIGEgZ2l2ZW4gYHlgIHZhbHVlIHdlIG5lZWQgdG8gc2V0IGBzdGF0PWlkZW50aXR5YCBhbmQgcHJvdmlkZSBib3RoIGB4YCBhbmQgYHlgIGluc2lkZSBgYWVzKClgIGB4YCBpcyBlaXRoZXIgY2hhcmFjdGVyIG9yIGZhY3RvciBhbmQgYHlgIGlzIG51bWVyaWMuCgpgYGB7cn0KIyBjcmVhdGUgYSBmcmVxdWVuY3kgdGFibGUKZnJlcXRhYmxlIDwtIHRhYmxlKG1wZyRtYW51ZmFjdHVyZXIpCmRmIDwtIGFzLmRhdGEuZnJhbWUudGFibGUoZnJlcXRhYmxlKQpoZWFkKGRmKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGYsIGFlcyhWYXIxLCBGcmVxKSkgKyAKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoID0gMC41LCBmaWxsPSJ0b21hdG8yIikgKyAKICBsYWJzKHRpdGxlPSJCYXIgQ2hhcnQiLCAKICAgICAgIHN1YnRpdGxlPSJNYW51ZmFjdHVyZXIgb2YgdmVoaWNsZXMiLCAKICAgICAgIGNhcHRpb249IlNvdXJjZTogRnJlcXVlbmN5IG9mIE1hbnVmYWN0dXJlcnMgZnJvbSAnbXBnJyBkYXRhc2V0IiwKICAgICAgIHggPSAiTWFudWZhY3R1cmVyIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NjUsIHZqdXN0PTAuNikpICAjIHRvIGdpdmUgeCBsYWJlbHMgYW4gYW5nbGUgZm9yIHJlYWRhYmlsaXR5IApgYGAKCioqRW1haWwgQ2FtcGFpZ24gRnVubmVsKiogZnJvbSBbVG9wIDUwIGdncGxvdDIgVmlzdWFsaXphdGlvbnNdKGh0dHA6Ly9yLXN0YXRpc3RpY3MuY28vVG9wNTAtR2dwbG90Mi1WaXN1YWxpemF0aW9ucy1NYXN0ZXJMaXN0LVItQ29kZS5odG1sKToKCmBgYHtyfQpvcHRpb25zKHNjaXBlbiA9IDk5OSkgICMgdHVybnMgb2ZmIHNjaWVudGlmaWMgbm90YXRpb25zIGxpa2UgMWUrNDAKb3B0aW9ucyhyZXByLnBsb3Qud2lkdGg9NywgcmVwci5wbG90LmhlaWdodD01KSAgIyBNb2RpZnlpbmcgdGhlIGNoYXJ0IHNpemUKCiMgUmVhZCBkYXRhCm9wdGlvbnMocmVhZHIubnVtX2NvbHVtbnMgPSAwKSAgIyB0dXJucyBvZmYgbWVzc2FnZXMgcHJpbnRlZCBieSByZWFkX2NzdgplbWFpbF9jYW1wYWlnbl9mdW5uZWwgPC0gcmVhZF9jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9zZWx2YTg2L2RhdGFzZXRzL21hc3Rlci9lbWFpbF9jYW1wYWlnbl9mdW5uZWwuY3N2IikKCiMgWCBBeGlzIEJyZWFrcyBhbmQgTGFiZWxzIApicmtzIDwtIHNlcSgtMTUwMDAwMDAsIDE1MDAwMDAwLCA1MDAwMDAwKQpsYmxzID0gcGFzdGUwKGFzLmNoYXJhY3RlcihjKHNlcSgxNSwgMCwgLTUpLCBzZXEoNSwgMTUsIDUpKSksICJtIikKCiMgUGxvdApnZ3Bsb3QoZW1haWxfY2FtcGFpZ25fZnVubmVsLCBhZXMoeCA9IFN0YWdlLCB5ID0gVXNlcnMsIGZpbGwgPSBHZW5kZXIpKSArICAgIyBGaWxsIGNvbHVtbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAuNikgKyAgICMgZHJhdyB0aGUgYmFycwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYnJrcywgICAjIEJyZWFrcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gbGJscykgKyAjIExhYmVscwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9mbGlwKCkgKyAgIyBGbGlwIGF4ZXMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9ICJFbWFpbCBDYW1wYWlnbiBGdW5uZWwiKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3R1ZnRlKCkgKyAgIyBUdWZ0ZSB0aGVtZSBmcm9tIGdnZm9ydGlmeQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSkgICMgQ2VudHJlIHBsb3QgdGl0bGUKYGBgCgojIyMgTGluZSBjaGFydApgYGB7cn0KZHRlbXAgPC0gZGF0YS5mcmFtZShtb250aHMgPSBmYWN0b3IocmVwKHN1YnN0cihtb250aC5uYW1lLDEsMyksIDQpLCBsZXZlbHMgPSBzdWJzdHIobW9udGgubmFtZSwxLDMpKSwKICAgICAgICAgICAgICAgICAgICBjaXR5ID0gcmVwKGMoIlRva3lvIiwgIk5ldyBZb3JrIiwgIkJlcmxpbiIsICJMb25kb24iKSwgZWFjaCA9IDEyKSwKICAgICAgICAgICAgICAgICAgICB0ZW1wID0gYyg3LjAsIDYuOSwgOS41LCAxNC41LCAxOC4yLCAyMS41LCAyNS4yLCAyNi41LCAyMy4zLCAxOC4zLCAxMy45LCA5LjYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLTAuMiwgMC44LCA1LjcsIDExLjMsIDE3LjAsIDIyLjAsIDI0LjgsIDI0LjEsIDIwLjEsIDE0LjEsIDguNiwgMi41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0wLjksIDAuNiwgMy41LCA4LjQsIDEzLjUsIDE3LjAsIDE4LjYsIDE3LjksIDE0LjMsIDkuMCwgMy45LCAxLjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMy45LCA0LjIsIDUuNywgOC41LCAxMS45LCAxNS4yLCAxNy4wLCAxNi42LCAxNC4yLCAxMC4zLCA2LjYsIDQuOCkpCgp0ZW1wIDwtIGdncGxvdChkdGVtcCwgYWVzKHggPSBtb250aHMsIHkgPSB0ZW1wLCBncm91cCA9IGNpdHksIGNvbG9yID0gY2l0eSkpICsKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDEuMSkgKyAKICBnZ3RpdGxlKCJNb250aGx5IEF2ZXJhZ2UgVGVtcGVyYXR1cmUiKSArCiAgdGhlbWVfaGMoc3R5bGUgPSAiZGFya3VuaWNhIikgKwogIHNjYWxlX2ZpbGxfaGMoImRhcmt1bmljYSIpCnRlbXAKYGBgCgojIEludGVyYWN0aXZlIHBsb3R0aW5nIHdpdGggUGxvdGx5CldlIGNhbiB1c2UgcGFja2FnZSAqKnBsb3RseSoqIG9uIHRvcCBvZiBhIGdncGxvdCBwbG90IHRvIGNyZWF0ZSBpbnRlcmFjdGl2ZSBjaGFydHMuIFBsb3RseSBpcyBhIHBvd2VyZnVsIHRvb2wgZm9yIGNyZWF0aW5nIGludGVyYWN0aXZlIGRhc2hib2FyZHMgYW5kIHBsb3RzIGFuZCB0aGVyZSBhcmUgZGlmZmVyZW50IHdheXMgdG8gdXNlIGl0LiBIZXJlIHdlIHdpbGwgb25seSBzaG93IGhvdyB0byBtYWtlIGdncGxvdHMgaW50byBhIHBsb3RseSBieSB1c2luZyBgZ2dwbG90bHkoKWAgZnVuY3Rpb24uIEZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IG90aGVyIHdheXMgdG8gbGV2ZXJhZ2UgdGhpcyBwYWNrYWdlIGdvIHRvIFtwbG95Lmx5XShodHRwczovL3Bsb3QubHkvKS4KCiMjIFNjYXR0ZXJwbG90CkxldCdzIHVzZSB0aGUgbW9zdCByZWNlbnQgcGxvdCB3ZSBjcmVhdGVkIHdpdGggV1NKIHRoZW1lIGFzIGFuIGV4YW1wbGU6CgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3RseShwMiArIHRoZW1lX3dzaigpICsgc2NhbGVfY29sb3VyX3dzaigiY29sb3JzNiIsICIiKSkgICMgU2FtZSBwbG90IHdpdGggZ2dwbG90bHkoKQpgYGAKCiMjIFRpbWUgU2VyaWVzClVzaW5nIGBnZW9tX2xpbmUoKWAsIGEgdGltZSBzZXJpZXMgKG9yIGxpbmUgY2hhcnQpIGNhbiBiZSBkcmF3bi4gRGF0YTogYGVjb25vbWljc2AgZnJvbSBnZ3Bsb3QyLgoKYGBge3J9CmhlYWQoZWNvbm9taWNzKQpgYGAKCgpgYGB7cn0KdHNfcGxvdCA8LSBnZ3Bsb3QoZWNvbm9taWNzLCBhZXMoeD1kYXRlKSkgKyAKZ2VvbV9saW5lKGFlcyh5PXBzYXZlcnQpKSArIAogIGxhYnModGl0bGU9IlVTIGVjb25vbWljIHRpbWUgc2VyaWVzIiwgCiAgICAgICBzdWJ0aXRsZSA9ICJQZXJzb25hbCBTYXZpbmdzIFJhdGUiLAogICAgICAgY2FwdGlvbj0iU291cmNlOiBFY29ub21pY3MiLCAKICAgICAgIHk9IlNhdmluZ3MgUmF0ZSAlIikgKwogIHRoZW1lX2NsYXNzaWMoKQoKZ2dwbG90bHkodHNfcGxvdCkgICMgU2FtZSBwbG90IHdpdGggZ2dwbG90bHkoKQpgYGAKCiMjIEJhciBjaGFydAoKYGBge3Igd2FybmluZz1GQUxTRX0KYmFyX3Bsb3QgPC0gZ2dwbG90KGRhdGEgPSBkaWFtb25kcykgKyAKICBnZW9tX2JhcihtYXBwaW5nID0gYWVzKHggPSBjdXQsIGZpbGwgPSBjbGFyaXR5KSwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzQxZjRmNCIsICIjNDFkOWY0IiwgIiM0MWJiZjQiLCAiIzQxOGVmNCIsICIjNDE1ZWY0IiwgIiM2YTQxZjQiLCAiIzk3NDFmNCIsICIjZjQ0MWYxIikpCgpnZ3Bsb3RseShiYXJfcGxvdCkgICMgU2FtZSBwbG90IHdpdGggZ2dwbG90bHkoKQpgYGAKCi0tLS0KCiMgQWRkaXRpb25hbCBSZWNvdXJzZXMKKiBFeGFtcGxlcyBvZiBlbGFib3JhdGUgY2hhcnRzOiBbVG9wIDUwIGdncGxvdDIgVmlzdWFsaXphdGlvbnNdKGh0dHA6Ly9yLXN0YXRpc3RpY3MuY28vVG9wNTAtR2dwbG90Mi1WaXN1YWxpemF0aW9ucy1NYXN0ZXJMaXN0LVItQ29kZS5odG1sKQoqIFRvIGdvIGJleW9uZCBnZ3Bsb3QyIGZ1bmN0aW9uYWxpdGllcyBjaGVjayBvdXQgdGhlc2UgZXh0ZW5zaW9uczogW2dncGxvdDIgZXh0ZW5zaW9uc10oaHR0cHM6Ly9leHRzLmdncGxvdDIudGlkeXZlcnNlLm9yZy9nYWxsZXJ5LykKKiAqZ2dwbG90Mi1jaGVhdHNoZWV0LnBkZiogaW4gdGhlIGNoZWF0c2hlZXRzIGRpcmVjdG9yeQoqIEhleCBjb2xvcgogICAgKiBTaW1wbHkgZ29vZ2xlICJoZXggY29sb3IgcGlja2VyIiBhbmQgdXNlIEdvb2dsZSdzIHRvb2wKKiBUaGVtZXMKICAgICogW2dndGhlbWVzXShodHRwczovL2dpdGh1Yi5jb20vanJub2xkL2dndGhlbWVzKSAtIEV4YW1wbGVzIFtoZXJlXShodHRwczovL21yYW4ubWljcm9zb2Z0LmNvbS9zbmFwc2hvdC8yMDE2LTEyLTAzL3dlYi9wYWNrYWdlcy9nZ3RoZW1lcy92aWduZXR0ZXMvZ2d0aGVtZXMuaHRtbCkKICAgICogW2dndGVjaF0oaHR0cHM6Ly9naXRodWIuY29tL3JpY2FyZG8tYmlvbi9nZ3RlY2gpCg==